package com.fly.core.ds;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.ExecutionException;

import org.apache.commons.dbutils.DbUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 数据源抽象类
 * 
 * @author 00fly
 * @version [版本号, 2018年9月27日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Slf4j
public abstract class BaseDataSource
{
    // 使用ThreadLocal存储当前线程中的Connection对象
    protected static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
    
    /**
     * 获取数据库连接
     * 
     * @return
     * @throws SQLException
     * @throws ExecutionException
     * @throws InterruptedException
     * @see [类、类#方法、类#成员]
     */
    public abstract Connection getConnection()
        throws SQLException;
    
    /**
     * 释放数据库连接
     * 
     * @see [类、类#方法、类#成员]
     */
    public void close(Connection connection)
    {
        log.info("◆◆◆◆释放资源: {}", connection);
        DbUtils.closeQuietly(connection);
        threadLocal.remove(); // 解除当前线程上绑定conn
    }
    
    /**
     * 开启事务
     * 
     * @throws SQLException
     */
    public void startTransaction()
        throws SQLException
    {
        Connection connection = threadLocal.get();
        if (connection == null)
        {
            connection = getConnection();
            connection.setAutoCommit(false); // 把事务提交方式改为手工提交
            threadLocal.set(connection); // 把 connection绑定到当前线程上
        }
        log.info("------开启事务: {}-------", connection);
    }
    
    /**
     * 提交事务并关闭连接
     * 
     * @throws SQLException
     * 
     */
    public void commitAndClose()
        throws SQLException
    {
        Connection connection = threadLocal.get();
        log.info("------提交事务: {}-------", connection);
        try
        {
            connection.commit();
        }
        finally
        {
            connection.setAutoCommit(true);
            DbUtils.closeQuietly(connection);
            threadLocal.remove(); // 解除当前线程上绑定conn
        }
    }
    
    /**
     * 回滚事务并关闭连接
     * 
     * @throws SQLException
     * 
     */
    public void rollbackAndClose()
        throws SQLException
    {
        Connection connection = threadLocal.get();
        log.info("------回滚事务: {}-------", connection);
        try
        {
            connection.rollback();
        }
        finally
        {
            connection.setAutoCommit(true);
            DbUtils.closeQuietly(connection);
            threadLocal.remove(); // 解除当前线程上绑定conn
        }
    }
}
